package com.flk.flkelasticsearch.service.service;

import com.flk.flkelasticsearch.entity.EsHotWordsParent;
import com.flk.flkelasticsearch.entity.EsNews;
import com.flk.flkelasticsearch.es.EsInfomation;
import com.flk.flkelasticsearch.es.MyElasticSearchTemplate;
import com.flk.flkelasticsearch.es.SearchResultSuggest;
import com.flk.flkelasticsearch.service.IFlkNewsService;
import io.searchbox.client.JestClient;
import io.searchbox.core.Search;
import io.searchbox.core.SearchResult;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.query.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.List;

/**
 * @author xxwy
 * on 2018/11/8 0008
 */
@Service
public class FlkNewsServiceImpl implements IFlkNewsService {

    @Autowired
    private MyElasticSearchTemplate myElasticSearchTemplate;

    @Autowired
    JestClient jestClient;

    private static final Logger logger = LoggerFactory.getLogger(FlkNewsServiceImpl.class);

    private static final String[] storeFields = {"title","platform","origin","type", "newsId", "createTime", "userId", "nickname","video","videoCover","cover","headimgurl"};

    /**
     * flk_news
     * {
     * "stored_fields": ["title","newsId","createTime","authorId],
     * "query": {
     * "bool": {
     * "must": [
     * {
     * "simple_query_string": {
     * "query": "好冷",
     * "fields": ["title","title.keyword","title.pinyin","code"]
     * }
     * }
     * ],
     * "filter": {
     * "term": {
     * "isDelete":0
     * }
     * }
     * }
     * }
     * }
     *
     * @param info
     * @return
     */
    @Override
    public List<EsNews> getTitleAndCode(String info, int size, int page) {
        QueryBuilder queryBuilder = new BoolQueryBuilder()
                .must(new SimpleQueryStringBuilder(info)
                        .field("title").field("title.keyword").field("title.pinyin").field("code").field("nickname"))
                .filter(new TermQueryBuilder("isDelete", 0));
        SearchQuery searchQuery = null;
        if (size != 0) {
            Pageable pageable = new PageRequest(page-1, size);
            searchQuery = new NativeSearchQueryBuilder()
                    .withQuery(queryBuilder).withFields(storeFields)
                    .withPageable(pageable).build();
        } else {
            searchQuery = new NativeSearchQueryBuilder()
                    .withQuery(queryBuilder).withFields(storeFields).build();
        }
        return myElasticSearchTemplate.queryForList(searchQuery, EsNews.class);
    }

    /**
     * flk_news 匹配文章标题的搜索
     * {
     * "stored_fields": ["title"],
     * "query": {
     * "bool": {
     * "should": [
     * {"match_phrase_prefix": {
     * "title.keyword": {
     * "max_expansions" : 5,
     * "query": "关键"
     * }
     * }
     * },
     * {"match_phrase_prefix": {
     * "title.pinyin_title": {
     * "max_expansions" : 5,
     * "query": "guanjianci",
     * "analyzer": "standard"
     * }
     * }
     * }
     * ],
     * "filter": {
     * "term": {
     * "isDelete":0
     * }
     * },
     * "minimum_should_match":1
     * }
     * }
     * }
     *
     * @param info
     * @return
     */
    @Override
    public List<Object> getBeforeTitle(String info, int size) {
        QueryBuilder queryBuilder = new BoolQueryBuilder()
                .should(new MatchPhrasePrefixQueryBuilder("title.keyword", info).maxExpansions(size))
                .should(new MatchPhrasePrefixQueryBuilder("title.pinyin_title", info)
                        .maxExpansions(size).analyzer("standard"))
                .filter(new TermQueryBuilder("isDelete", 0))
                .minimumShouldMatch(1);
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(queryBuilder).withFields("title")
                .withIndices("flk_news_xxwy").withTypes("doc").build();
        return myElasticSearchTemplate.queryForList(searchQuery, Object.class);
    }

    /**
     * {
     * "suggest": {
     *  "hotkey-suggest" : {
     *      "prefix" : "你在",
     *      "completion" : {
     *          "field" : "hotwords",
     *          "skip_duplicates": true
     *      }
     *    }
     *  }
     * }
     *
     * @param info
     * @return
     */
    @Override
    public List<String> getHotInfo(String info) throws IOException {

        String json = "{\n" +
                "  \"suggest\": {\n" +
                "    \"hotkey-suggest\" : {\n" +
                "      \"prefix\" : \""+info+"\",\n" +
                "      \"completion\" : {\n" +
                "        \"field\" : \"hotwords\",\n" +
                "        \"skip_duplicates\": true\n" +
                "      }\n" +
                "    }\n" +
                "  }\n" +
                "}";

        Search search = new Search.Builder(json).addIndex(EsInfomation.FLX_HOTWORD_NEWS).addType(EsInfomation.DOC).build();
        SearchResult result = jestClient.execute(search);
        List<String> hotwords = null;
        if(result.getResponseCode() == 200){
            //解析result
            hotwords = SearchResultSuggest.parseSuggestResponse(result, "hotkey-suggest", "hotwords");
        }
        return hotwords;
    }

    /**
     * {
     *     "hotwords" : {
     *       "input": "你在吗，大傻子",
     *        "weight" :21
     *     }
     * }
     * 添加热词/增加热词的热度
     * @param info
     */
    @Override
    @Transactional
    public void saveOrUpdateHotWords(String info, String indexName) {
        if (!info.matches("^[a-zA-Z]+$")) {
            Integer sort = countSort(info,indexName);
            String source = "{\n" +
                    "  \"hotwords\": {\n" +
                    "      \"input\": \""+info+"\",\n" +
                    "      \"weight\" : "+sort+"\n" +
                    "    }\n" +
                    "}";
            IndexQuery indexQuery = new IndexQueryBuilder()
                    .withIndexName(indexName)
                    .withType(EsInfomation.DOC)
                    .withId(info)
                    .withVersion(Long.parseLong(sort.toString()))
                    .withSource(source).build();
            myElasticSearchTemplate.index(indexQuery);
            logger.info("添加热词");
        }
    }

    @Transactional
    public Integer countSort(String info,String indexName) {
        GetQuery getQuery = new GetQuery();
        getQuery.setId(info);
        if(myElasticSearchTemplate.indexExists(indexName)) {
            EsHotWordsParent esHotWords = myElasticSearchTemplate.queryForObject(getQuery, indexName, EsHotWordsParent.class);
            if (esHotWords != null && esHotWords.getHotwords() != null) {
                myElasticSearchTemplate.delete(indexName, EsInfomation.DOC, info);
                return esHotWords.getHotwords().getWeight() + 1;
            }
        }
        return 1;
    }



}